1
2
3
4 package joeq.Compiler.Quad.x86;
5
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.LinkedList;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14 import joeq.Allocator.CodeAllocator;
15 import joeq.Allocator.DefaultCodeAllocator;
16 import joeq.Allocator.DefaultHeapAllocator;
17 import joeq.Allocator.HeapAllocator;
18 import joeq.Allocator.ObjectLayout;
19 import joeq.Assembler.Code2CodeReference;
20 import joeq.Assembler.Code2HeapReference;
21 import joeq.Assembler.DirectBindCall;
22 import joeq.Assembler.x86.x86;
23 import joeq.Assembler.x86.x86Assembler;
24 import joeq.Assembler.x86.x86Constants;
25 import joeq.Bootstrap.BootstrapCodeAllocator;
26 import joeq.Bootstrap.SinglePassBootImage;
27 import joeq.Class.jq_Array;
28 import joeq.Class.jq_Class;
29 import joeq.Class.jq_CompiledCode;
30 import joeq.Class.jq_InstanceField;
31 import joeq.Class.jq_InstanceMethod;
32 import joeq.Class.jq_Method;
33 import joeq.Class.jq_Primitive;
34 import joeq.Class.jq_StaticField;
35 import joeq.Class.jq_StaticMethod;
36 import joeq.Class.jq_TryCatch;
37 import joeq.Class.jq_Type;
38 import joeq.ClassLib.ClassLibInterface;
39 import joeq.Compiler.CompilerInterface;
40 import joeq.Compiler.BytecodeAnalysis.BytecodeVisitor;
41 import joeq.Compiler.Quad.BasicBlock;
42 import joeq.Compiler.Quad.BasicBlockVisitor;
43 import joeq.Compiler.Quad.CodeCache;
44 import joeq.Compiler.Quad.ControlFlowGraph;
45 import joeq.Compiler.Quad.ExceptionHandler;
46 import joeq.Compiler.Quad.ExceptionHandlerList;
47 import joeq.Compiler.Quad.Operand;
48 import joeq.Compiler.Quad.Quad;
49 import joeq.Compiler.Quad.QuadIterator;
50 import joeq.Compiler.Quad.QuadVisitor;
51 import joeq.Compiler.Quad.RegisterFactory;
52 import joeq.Compiler.Quad.Operand.AConstOperand;
53 import joeq.Compiler.Quad.Operand.BasicBlockTableOperand;
54 import joeq.Compiler.Quad.Operand.Const4Operand;
55 import joeq.Compiler.Quad.Operand.Const8Operand;
56 import joeq.Compiler.Quad.Operand.ParamListOperand;
57 import joeq.Compiler.Quad.Operand.RegisterOperand;
58 import joeq.Compiler.Quad.Operator.ALength;
59 import joeq.Compiler.Quad.Operator.ALoad;
60 import joeq.Compiler.Quad.Operator.AStore;
61 import joeq.Compiler.Quad.Operator.Binary;
62 import joeq.Compiler.Quad.Operator.BoundsCheck;
63 import joeq.Compiler.Quad.Operator.CheckCast;
64 import joeq.Compiler.Quad.Operator.Getfield;
65 import joeq.Compiler.Quad.Operator.Getstatic;
66 import joeq.Compiler.Quad.Operator.Goto;
67 import joeq.Compiler.Quad.Operator.InstanceOf;
68 import joeq.Compiler.Quad.Operator.IntIfCmp;
69 import joeq.Compiler.Quad.Operator.Invoke;
70 import joeq.Compiler.Quad.Operator.Jsr;
71 import joeq.Compiler.Quad.Operator.LookupSwitch;
72 import joeq.Compiler.Quad.Operator.MemLoad;
73 import joeq.Compiler.Quad.Operator.MemStore;
74 import joeq.Compiler.Quad.Operator.Monitor;
75 import joeq.Compiler.Quad.Operator.Move;
76 import joeq.Compiler.Quad.Operator.New;
77 import joeq.Compiler.Quad.Operator.NewArray;
78 import joeq.Compiler.Quad.Operator.NullCheck;
79 import joeq.Compiler.Quad.Operator.Putfield;
80 import joeq.Compiler.Quad.Operator.Putstatic;
81 import joeq.Compiler.Quad.Operator.Ret;
82 import joeq.Compiler.Quad.Operator.Return;
83 import joeq.Compiler.Quad.Operator.Special;
84 import joeq.Compiler.Quad.Operator.StoreCheck;
85 import joeq.Compiler.Quad.Operator.TableSwitch;
86 import joeq.Compiler.Quad.Operator.Unary;
87 import joeq.Compiler.Quad.Operator.ZeroCheck;
88 import joeq.Compiler.Quad.RegisterFactory.Register;
89 import joeq.Compiler.Reference.x86.x86ReferenceCompiler;
90 import joeq.Compiler.Reference.x86.x86ReferenceLinker;
91 import joeq.Main.HostedVM;
92 import joeq.Main.jq;
93 import joeq.Memory.CodeAddress;
94 import joeq.Memory.HeapAddress;
95 import joeq.Runtime.ExceptionDeliverer;
96 import joeq.Runtime.MathSupport;
97 import joeq.Runtime.ObjectTraverser;
98 import joeq.Runtime.Reflection;
99 import joeq.Runtime.SystemInterface;
100 import joeq.Runtime.TypeCheck;
101 import joeq.Runtime.Unsafe;
102 import joeq.Scheduler.jq_x86RegisterState;
103 import jwutil.collections.AppendIterator;
104 import jwutil.strings.Strings;
105 import jwutil.util.Assert;
106
107 /***
108 * @author John Whaley <jwhaley@alum.mit.edu>
109 * @version $Id: SimpleCompiler.java 1941 2004-09-30 03:37:06Z joewhaley $
110 */
111 public class SimpleCompiler implements x86Constants, BasicBlockVisitor, QuadVisitor {
112
113 static {
114
115 jq_x86RegisterState.initFactory();
116 }
117
118 public static class Factory implements CompilerInterface {
119 public static final Factory INSTANCE = new Factory();
120 public Factory() {}
121 public jq_CompiledCode compile(jq_Method m) {
122 return new SimpleCompiler(m).compile();
123 }
124 public jq_CompiledCode generate_compile_stub(jq_Method m) {
125 return x86ReferenceCompiler.generate_compile_stub(m);
126 }
127 public jq_StaticMethod getInvokestaticLinkMethod() {
128 return x86ReferenceLinker._invokestatic;
129 }
130 public jq_StaticMethod getInvokespecialLinkMethod() {
131 return x86ReferenceLinker._invokespecial;
132 }
133 public jq_StaticMethod getInvokeinterfaceLinkMethod() {
134 return x86ReferenceLinker._invokeinterface;
135 }
136 }
137
138 public static
139 public static
140
141 public static final Set TraceMethod_MethodNames = new HashSet();
142 public static final Set TraceMethod_ClassNames = new HashSet();
143 public static final Set TraceQuad_MethodNames = new HashSet();
144 public static final Set TraceQuad_ClassNames = new HashSet();
145
146 public boolean TraceQuads;
147 public boolean TraceMethods;
148 public boolean TraceArguments;
149
150 public static final int DEFAULT_ALIGNMENT = 32;
151
152 public ControlFlowGraph cfg;
153 public jq_Method method;
154 public Map registerLocations;
155
156 public boolean TRACE;
157
158 public SimpleCompiler() { }
159 public SimpleCompiler(ControlFlowGraph cfg) { this.init(cfg); }
160 public SimpleCompiler(jq_Method m) { this.init(m); }
161
162 public void init(jq_Method m) {
163 init(CodeCache.getCode(m));
164 }
165
166 public void init(ControlFlowGraph cfg) {
167 this.cfg = cfg;
168 method = cfg.getMethod();
169 TRACE = ALWAYS_TRACE;
170 if (TraceQuad_MethodNames.contains(method.getName().toString())) {
171 TraceQuads = true;
172 TraceMethods = true;
173 } else if (TraceQuad_ClassNames.contains(method.getDeclaringClass().getName().toString())) {
174 TraceQuads = true;
175 TraceMethods = true;
176 } else if (TraceMethod_MethodNames.contains(method.getName().toString())) {
177 TraceQuads = false;
178 TraceMethods = true;
179 } else if (TraceMethod_ClassNames.contains(method.getDeclaringClass().getName().toString())) {
180 TraceQuads = false;
181 TraceMethods = true;
182 } else {
183 TraceQuads = false;
184 TraceMethods = false;
185 }
186 TraceArguments = false;
187 registerLocations = new HashMap();
188 code_relocs = new LinkedList();
189 data_relocs = new LinkedList();
190 }
191
192 public String toString() {
193 return "x86Quad/"+Strings.left(method.getName().toString(), 10);
194 }
195
196 private x86Assembler asm;
197 private int n_paramwords;
198
199 private List code_relocs;
200 private List data_relocs;
201
202 public final void emitCallRelative(jq_Method target) { emitCallRelative(target, asm, code_relocs); }
203 public static final void emitCallRelative(jq_Method target, x86Assembler asm, List code_relocs) {
204 asm.emitCALL_rel32(x86.CALL_rel32, 0);
205 DirectBindCall r = new DirectBindCall((CodeAddress) asm.getCurrentAddress().offset(-4), target);
206 code_relocs.add(r);
207 if (ALWAYS_TRACE) System.out.println("Direct bind call: "+r);
208 }
209 public final void emitPushAddressOf(Object o) { emitPushAddressOf(o, asm, data_relocs); }
210 public static final void emitPushAddressOf(Object o, x86Assembler asm, List data_relocs) {
211 if (o != null) {
212 HeapAddress addr = HeapAddress.addressOf(o);
213 asm.emit1_Imm32(x86.PUSH_i32, addr.to32BitValue());
214 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
215 data_relocs.add(r);
216 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
217 } else {
218 asm.emit1_Imm8(x86.PUSH_i8, (byte)0);
219 }
220 }
221 public final void emitPushMemory(jq_StaticField f) { emitPushMemory(f, asm, data_relocs); }
222 public static final void emitPushMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
223 HeapAddress addr = f.getAddress();
224 asm.emit2_Mem(x86.PUSH_m, addr.to32BitValue());
225 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
226 data_relocs.add(r);
227 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
228 }
229 public final void emitPushMemory8(jq_StaticField f) { emitPushMemory8(f, asm, data_relocs); }
230 public static final void emitPushMemory8(jq_StaticField f, x86Assembler asm, List data_relocs) {
231 HeapAddress addr = f.getAddress();
232 asm.emit2_Mem(x86.PUSH_m, addr.offset(4).to32BitValue());
233 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), (HeapAddress) addr.offset(4));
234 data_relocs.add(r);
235 asm.emit2_Mem(x86.PUSH_m, addr.to32BitValue());
236 r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
237 data_relocs.add(r);
238 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
239 }
240 public final void emitPopMemory(jq_StaticField f) { emitPopMemory(f, asm, data_relocs); }
241 public static final void emitPopMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
242 HeapAddress addr = f.getAddress();
243 asm.emit2_Mem(x86.POP_m, addr.to32BitValue());
244 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
245 data_relocs.add(r);
246 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
247 }
248 public final void emitPopMemory8(jq_StaticField f) { emitPopMemory8(f, asm, data_relocs); }
249 public static final void emitPopMemory8(jq_StaticField f, x86Assembler asm, List data_relocs) {
250 HeapAddress addr = f.getAddress();
251 asm.emit2_Mem(x86.POP_m, addr.to32BitValue());
252 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
253 data_relocs.add(r);
254 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
255 asm.emit2_Mem(x86.POP_m, addr.offset(4).to32BitValue());
256 r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), (HeapAddress) addr.offset(4));
257 data_relocs.add(r);
258 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
259 }
260 public final void emitCallMemory(jq_StaticField f) { emitCallMemory(f, asm, data_relocs); }
261 public static final void emitCallMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
262 HeapAddress addr = f.getAddress();
263 asm.emit2_Mem(x86.CALL_m, addr.to32BitValue());
264 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
265 data_relocs.add(r);
266 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
267 }
268 public final void emitFLD64(jq_StaticField f) { emitFLD64(f, asm, data_relocs); }
269 public static final void emitFLD64(jq_StaticField f, x86Assembler asm, List data_relocs) {
270 HeapAddress addr = f.getAddress();
271 asm.emit2_Mem(x86.FLD_m64, addr.to32BitValue());
272 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
273 data_relocs.add(r);
274 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
275 }
276
277 public final List getCodeRelocs() { return code_relocs; }
278 public final List getDataRelocs() { return data_relocs; }
279
280 public static final jq_CompiledCode generate_compile_stub(jq_Method method) {
281 if (TRACE_STUBS) System.out.println("x86 Quad Compiler: generating compile stub for "+method);
282 x86Assembler asm = new x86Assembler(0, 24, 0, DEFAULT_ALIGNMENT);
283 asm.setEntrypoint();
284 List code_relocs = new LinkedList();
285 List data_relocs = new LinkedList();
286 if (TRACE_STUBS) {
287 emitPushAddressOf(SystemInterface.toCString("Stub compile: "+method), asm, data_relocs);
288 emitCallMemory(SystemInterface._debugwriteln, asm, data_relocs);
289 }
290 emitPushAddressOf(method, asm, data_relocs);
291 emitCallRelative(jq_Method._compile, asm, code_relocs);
292 asm.emit2_Mem(x86.JMP_m, jq_CompiledCode._entrypoint.getOffset(), EAX);
293
294 return asm.getCodeBuffer().allocateCodeBlock(null, null, null, null, 0, code_relocs, data_relocs);
295 }
296
297 int getParamOffset(int i) {
298 Assert._assert(i < n_paramwords);
299 return (n_paramwords-i+1)<<2;
300 }
301
302 int getStackOffset(RegisterOperand r) { return getStackOffset(r.getRegister()); }
303
304 int getStackOffset(Register r) {
305 Integer i = (Integer) registerLocations.get(r);
306 return i.intValue();
307 }
308
309 int getStackFrameWords() {
310 return cfg.getRegisterFactory().size();
311 }
312
313 void initializeRegisterLocations() {
314 int current = -((getStackFrameWords()) << 2);
315 RegisterFactory rf = cfg.getRegisterFactory();
316 for (Iterator i=rf.iterator(); i.hasNext(); current += 4) {
317 Register r = (Register) i.next();
318 registerLocations.put(r, new Integer(current));
319 if (TRACE) System.out.println("Register: "+r+" offset: "+current);
320 }
321 Assert._assert(current == 0);
322 }
323
324
325 public final jq_CompiledCode compile() {
326 if (TRACE) System.out.println("x86 Quad Compiler: compiling "+method);
327
328
329 if (jq.RunningNative)
330 Unsafe.getThreadBlock().disableThreadSwitch();
331
332 try {
333
334 this.initializeRegisterLocations();
335
336 int quadcount = 0;
337 for (QuadIterator i=new QuadIterator(cfg); i.hasNext(); i.next())
338 ++quadcount;
339
340 asm = new x86Assembler(quadcount, quadcount*8, 5, DEFAULT_ALIGNMENT);
341 asm.skip(5);
342 asm.setEntrypoint();
343 jq_Type[] params = method.getParamTypes();
344 n_paramwords = method.getParamWords();
345 int n_localwords = getStackFrameWords();
346
347
348
349
350
351
352
353
354
355
356
357
358 asm.emitShort_Reg(x86.PUSH_r, EBP);
359 asm.emit2_Reg_Reg(x86.MOV_r_r32, EBP, ESP);
360 asm.emit2_Reg_Mem(x86.LEA, ESP, -n_localwords<<2, ESP);
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376 if (TraceMethods) {
377 emitPushAddressOf(SystemInterface.toCString("Entering: "+method));
378 emitCallMemory(SystemInterface._debugwriteln);
379 }
380
381 RegisterFactory rf = cfg.getRegisterFactory();
382 for (int i=0, j=0; i<params.length; ++i, ++j) {
383 if (params[i].getReferenceSize() == 8) {
384 int param_offset = getParamOffset(j+1);
385 int stack_offset = getStackOffset(rf.getOrCreateLocal(j, params[i]));
386 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, param_offset, EBP);
387 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, stack_offset, EBP);
388 param_offset = getParamOffset(j);
389 stack_offset = getStackOffset(rf.getOrCreateLocal(j+1, params[i]));
390 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, param_offset, EBP);
391 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, stack_offset, EBP);
392 ++j;
393 } else {
394 int param_offset = getParamOffset(j);
395 int stack_offset = getStackOffset(rf.getOrCreateLocal(j, params[i]));
396 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, param_offset, EBP);
397 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, stack_offset, EBP);
398 }
399 }
400
401
402 if (method.isSynchronized()) {
403 if (method.isStatic()) {
404 if (TraceQuads) {
405 emitPushAddressOf(SystemInterface.toCString("entry: STATIC SYNCH ENTER"));
406 emitCallMemory(SystemInterface._debugwriteln);
407 }
408
409 Class c = Reflection.getJDKType(method.getDeclaringClass());
410 Assert._assert(c != null);
411 emitPushAddressOf(c);
412 } else {
413 if (TraceQuads) {
414 emitPushAddressOf(SystemInterface.toCString("entry: INSTANCE SYNCH ENTER"));
415 emitCallMemory(SystemInterface._debugwriteln);
416 }
417
418 asm.emit2_Mem(x86.PUSH_m, getParamOffset(0), EBP);
419 }
420 emitCallRelative(joeq.Runtime.Monitor._monitorenter);
421 }
422
423
424 cfg.visitBasicBlocks(this);
425
426
427 List tcs = new LinkedList();
428 for (Iterator i=cfg.reversePostOrderIterator(); i.hasNext(); ) {
429 BasicBlock bb = (BasicBlock) i.next();
430 ExceptionHandlerList ex = bb.getExceptionHandlers();
431 int start = asm.getBranchTarget(bb);
432 int end = asm.getBranchTarget(new Integer(bb.getID()));
433 for (Iterator j=ex.exceptionHandlerIterator(); j.hasNext(); ) {
434 ExceptionHandler e = (ExceptionHandler) j.next();
435 int handler = asm.getBranchTarget(e.getEntry());
436 Iterator k = e.getEntry().iterator();
437 Assert._assert(k.hasNext());
438 Quad x = (Quad) k.next();
439 Assert._assert(x.getOperator() instanceof Special.GET_EXCEPTION);
440 RegisterOperand rop = (RegisterOperand) Special.getOp1(x);
441 jq_TryCatch tc = new jq_TryCatch(start, end, handler, e.getExceptionType(), getStackOffset(rop));
442 tcs.add(tc);
443 }
444 }
445 jq_TryCatch[] tcs_a = (jq_TryCatch[]) tcs.toArray(new jq_TryCatch[tcs.size()]);
446
447
448
449
450 jq_CompiledCode code;
451 code = asm.getCodeBuffer().allocateCodeBlock(method, tcs_a, null,
452 x86QuadExceptionDeliverer.INSTANCE,
453 n_localwords*4,
454 code_relocs, data_relocs);
455 CodeCache.free(cfg);
456
457 if (jq.RunningNative)
458 Unsafe.getThreadBlock().enableThreadSwitch();
459 return code;
460 } catch (RuntimeException x) {
461 SystemInterface.debugwriteln("Exception occurred while compiling: "+method);
462 SystemInterface.debugwriteln("Exception: "+x);
463 x.printStackTrace();
464 SystemInterface.die(-1);
465 return null;
466 }
467 }
468
469 public void visitBasicBlock(BasicBlock bb) {
470
471 asm.recordBranchTarget(bb);
472
473 asm.resolveForwardBranches(bb);
474
475 for (joeq.Util.Templates.ListIterator.Quad i=bb.iterator(); i.hasNext(); ) {
476 this.handled = false;
477 Quad q = i.nextQuad();
478 q.accept(this);
479 Assert._assert(handled, q.toString());
480 }
481 if (bb.getFallthroughSuccessor() != null)
482 branchHelper(BytecodeVisitor.CMP_UNCOND, bb.getFallthroughSuccessor());
483
484 asm.recordBranchTarget(new Integer(bb.getID()));
485 }
486
487 public static byte THREAD_BLOCK_PREFIX = x86.PREFIX_FS;
488 public static int THREAD_BLOCK_OFFSET = 0x14;
489
490 private int getPairedRegister(int register) {
491 switch (register) {
492 case EAX: return EDX;
493 case EBX: return ECX;
494 case ECX: return EBX;
495 case EDX: return EAX;
496 default: Assert.UNREACHABLE(); return 0;
497 }
498 }
499
500 private void loadOperand(Operand o, int register) {
501 if (o instanceof RegisterOperand) {
502 int src = getStackOffset((RegisterOperand) o);
503 asm.emit2_Reg_Mem(x86.MOV_r_m32, register, src, EBP);
504 if (((RegisterOperand) o).getType().getReferenceSize() == 8) {
505 asm.emit2_Reg_Mem(x86.MOV_r_m32, getPairedRegister(register), src+4, EBP);
506 }
507 } else if (o instanceof AConstOperand) {
508 Object a = ((AConstOperand) o).getValue();
509 emitPushAddressOf(a);
510 asm.emitShort_Reg(x86.POP_r, register);
511 } else if (o instanceof Const4Operand) {
512 int v = ((Const4Operand) o).getBits();
513 asm.emitShort_Reg_Imm(x86.MOV_r_i32, register, v);
514 } else if (o instanceof Const8Operand) {
515 long v = ((Const8Operand) o).getBits();
516 asm.emitShort_Reg_Imm(x86.MOV_r_i32, register, (int)(v));
517 asm.emitShort_Reg_Imm(x86.MOV_r_i32, getPairedRegister(register), (int)(v>>32));
518 } else {
519 Assert.UNREACHABLE("x86 register "+register+": "+o);
520 }
521 }
522
523 private void storeOperand(RegisterOperand o, int register) {
524 int dest = getStackOffset(o);
525 asm.emit2_Reg_Mem(x86.MOV_m_r32, register, dest, EBP);
526 if (o.getType().getReferenceSize() == 8) {
527 asm.emit2_Reg_Mem(x86.MOV_m_r32, getPairedRegister(register), dest+4, EBP);
528 }
529 }
530
531 /***
532 * @see joeq.Compiler.Quad.QuadVisitor#visitExceptionThrower(joeq.Compiler.Quad.Quad)
533 */
534 public void visitExceptionThrower(Quad obj) {
535 if (TRACE) System.out.println(this+" PEI: "+obj);
536 }
537 /***
538 * @see joeq.Compiler.Quad.QuadVisitor#visitLoad(joeq.Compiler.Quad.Quad)
539 */
540 public void visitLoad(Quad obj) {
541 if (TRACE) System.out.println(this+" Load: "+obj);
542 }
543 /***
544 * @see joeq.Compiler.Quad.QuadVisitor#visitStore(joeq.Compiler.Quad.Quad)
545 */
546 public void visitStore(Quad obj) {
547 if (TRACE) System.out.println(this+" Store: "+obj);
548 }
549 /***
550 * @see joeq.Compiler.Quad.QuadVisitor#visitBranch(joeq.Compiler.Quad.Quad)
551 */
552 public void visitBranch(Quad obj) {
553 if (TRACE) System.out.println(this+" Branch: "+obj);
554 }
555 /***
556 * @see joeq.Compiler.Quad.QuadVisitor#visitCondBranch(joeq.Compiler.Quad.Quad)
557 */
558 public void visitCondBranch(Quad obj) {
559 if (TRACE) System.out.println(this+" CondBranch: "+obj);
560 }
561 /***
562 * @see joeq.Compiler.Quad.QuadVisitor#visitCheck(joeq.Compiler.Quad.Quad)
563 */
564 public void visitCheck(Quad obj) {
565 if (TRACE) System.out.println(this+" Check: "+obj);
566 }
567 /***
568 * @see joeq.Compiler.Quad.QuadVisitor#visitStaticField(joeq.Compiler.Quad.Quad)
569 */
570 public void visitStaticField(Quad obj) {
571 if (TRACE) System.out.println(this+" StaticField: "+obj);
572 }
573 /***
574 * @see joeq.Compiler.Quad.QuadVisitor#visitInstanceField(joeq.Compiler.Quad.Quad)
575 */
576 public void visitInstanceField(Quad obj) {
577 if (TRACE) System.out.println(this+" InstanceField: "+obj);
578 }
579 /***
580 * @see joeq.Compiler.Quad.QuadVisitor#visitArray(joeq.Compiler.Quad.Quad)
581 */
582 public void visitArray(Quad obj) {
583 if (TRACE) System.out.println(this+" Array: "+obj);
584 }
585 /***
586 * @see joeq.Compiler.Quad.QuadVisitor#visitAllocation(joeq.Compiler.Quad.Quad)
587 */
588 public void visitAllocation(Quad obj) {
589 if (TRACE) System.out.println(this+" Allocation: "+obj);
590 }
591 /***
592 * @see joeq.Compiler.Quad.QuadVisitor#visitTypeCheck(joeq.Compiler.Quad.Quad)
593 */
594 public void visitTypeCheck(Quad obj) {
595 if (TRACE) System.out.println(this+" TypeCheck: "+obj);
596 }
597 /***
598 * @see joeq.Compiler.Quad.QuadVisitor#visitALoad(joeq.Compiler.Quad.Quad)
599 */
600 public void visitALoad(Quad obj) {
601 if (TRACE) System.out.println(this+" ALoad: "+obj);
602 loadOperand(ALoad.getBase(obj), EAX);
603 loadOperand(ALoad.getIndex(obj), EBX);
604 jq_Type t = ((ALoad) obj.getOperator()).getType();
605 int scale = t.getReferenceSize();
606 switch (scale) {
607 case 4:
608 asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, EAX, EBX, SCALE_4, ObjectLayout.ARRAY_ELEMENT_OFFSET);
609 break;
610 case 2:
611 if (t == jq_Primitive.CHAR)
612 asm.emit3_Reg_Mem(x86.MOVZX_r_m16, ECX, EAX, EBX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
613 else
614 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, ECX, EAX, EBX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
615 break;
616 case 1:
617 asm.emit3_Reg_Mem(x86.MOVSX_r_m8, ECX, EAX, EBX, SCALE_1, ObjectLayout.ARRAY_ELEMENT_OFFSET);
618 break;
619 case 8:
620 asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET);
621 asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET+4);
622 break;
623 default: Assert.UNREACHABLE(); break;
624 }
625 storeOperand(ALoad.getDest(obj), ECX);
626 this.handled = true;
627 }
628 /***
629 * @see joeq.Compiler.Quad.QuadVisitor#visitAStore(joeq.Compiler.Quad.Quad)
630 */
631 public void visitAStore(Quad obj) {
632 if (TRACE) System.out.println(this+" AStore: "+obj);
633
634 loadOperand(AStore.getBase(obj), EAX);
635 loadOperand(AStore.getIndex(obj), EDX);
636 loadOperand(AStore.getValue(obj), ECX);
637
638 jq_Type t = ((AStore) obj.getOperator()).getType();
639 int scale = t.getReferenceSize();
640 switch (scale) {
641 case 4:
642 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EDX, SCALE_4, ObjectLayout.ARRAY_ELEMENT_OFFSET);
643 break;
644 case 2:
645 asm.emitprefix(x86.PREFIX_16BIT);
646 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EDX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
647 break;
648 case 1:
649 asm.emit2_Reg_Mem(x86.MOV_m_r8, ECX, EAX, EDX, SCALE_1, ObjectLayout.ARRAY_ELEMENT_OFFSET);
650 break;
651 case 8:
652 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EDX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET );
653 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, EAX, EDX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET+4);
654 break;
655 default: Assert.UNREACHABLE(); break;
656 }
657 this.handled = true;
658 }
659 /***
660 * @see joeq.Compiler.Quad.QuadVisitor#visitALength(joeq.Compiler.Quad.Quad)
661 */
662 public void visitALength(Quad obj) {
663 if (TRACE) System.out.println(this+" ALength: "+obj);
664 loadOperand(ALength.getSrc(obj), EAX);
665 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
666 storeOperand(ALength.getDest(obj), EAX);
667 this.handled = true;
668 }
669 /***
670 * @see joeq.Compiler.Quad.QuadVisitor#visitBinary(joeq.Compiler.Quad.Quad)
671 */
672 public void visitBinary(Quad obj) {
673 if (TRACE) System.out.println(this+" Binary: "+obj);
674 loadOperand(Binary.getSrc1(obj), EAX);
675 loadOperand(Binary.getSrc2(obj), EBX);
676 Binary op = (Binary) obj.getOperator();
677 if (op instanceof Binary.ADD_I || op instanceof Binary.ADD_P) {
678 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, EBX);
679 } else if (op instanceof Binary.SUB_I || op instanceof Binary.SUB_P) {
680 asm.emitARITH_Reg_Reg(x86.SUB_r_r32, EAX, EBX);
681 } else if (op instanceof Binary.MUL_I) {
682 asm.emit2_Reg(x86.IMUL_rda_r32, EBX);
683 } else if (op instanceof Binary.DIV_I) {
684 asm.emit1(x86.CWD);
685 asm.emit2_Reg(x86.IDIV_r32, EBX);
686 } else if (op instanceof Binary.REM_I) {
687 asm.emit1(x86.CWD);
688 asm.emit2_Reg(x86.IDIV_r32, EBX);
689 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
690 } else if (op instanceof Binary.AND_I) {
691 asm.emitARITH_Reg_Reg(x86.AND_r_r32, EAX, EBX);
692 } else if (op instanceof Binary.OR_I) {
693 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, EBX);
694 } else if (op instanceof Binary.XOR_I) {
695 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EBX);
696 } else if (op instanceof Binary.ADD_L) {
697 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, EBX);
698 asm.emitARITH_Reg_Reg(x86.ADC_r_r32, EDX, ECX);
699 } else if (op instanceof Binary.SUB_L) {
700 asm.emitARITH_Reg_Reg(x86.SUB_r_r32, EAX, EBX);
701 asm.emitARITH_Reg_Reg(x86.SBB_r_r32, EDX, ECX);
702 } else if (op instanceof Binary.MUL_L) {
703 asm.emit2_Reg_Reg(x86.MOV_r_r32, ESI, EAX);
704 asm.emit2_Reg_Reg(x86.MOV_r_r32, EDI, EDX);
705 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EDX, ECX);
706 asm.emitCJUMP_Short(x86.JNE, (byte)0);
707 int cloc = asm.getCurrentOffset();
708 asm.emit2_Reg(x86.MUL_rda_r32, EBX);
709 asm.emitJUMP_Short(x86.JMP, (byte)0);
710 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
711 cloc = asm.getCurrentOffset();
712 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI);
713 asm.emit2_Reg(x86.MUL_rda_r32, ECX);
714 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EAX);
715 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDI);
716 asm.emit2_Reg(x86.MUL_rda_r32, EBX);
717 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, ECX, EAX);
718 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI);
719 asm.emit2_Reg(x86.MUL_rda_r32, EBX);
720 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EDX, ECX);
721 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
722 } else if (op instanceof Binary.DIV_L) {
723 asm.emitShort_Reg(x86.PUSH_r, EDX);
724 asm.emitShort_Reg(x86.PUSH_r, EAX);
725 asm.emitShort_Reg(x86.PUSH_r, ECX);
726 asm.emitShort_Reg(x86.PUSH_r, EBX);
727 emitCallRelative(MathSupport._ldiv);
728 } else if (op instanceof Binary.REM_L) {
729 asm.emitShort_Reg(x86.PUSH_r, EDX);
730 asm.emitShort_Reg(x86.PUSH_r, EAX);
731 asm.emitShort_Reg(x86.PUSH_r, ECX);
732 asm.emitShort_Reg(x86.PUSH_r, EBX);
733 emitCallRelative(MathSupport._lrem);
734 } else if (op instanceof Binary.AND_L) {
735 asm.emitARITH_Reg_Reg(x86.AND_r_r32, EAX, EBX);
736 asm.emitARITH_Reg_Reg(x86.AND_r_r32, EDX, ECX);
737 } else if (op instanceof Binary.OR_L) {
738 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, EBX);
739 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EDX, ECX);
740 } else if (op instanceof Binary.XOR_L) {
741 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EBX);
742 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EDX, ECX);
743 } else if (op instanceof Binary.ADD_F) {
744 asm.emitShort_Reg(x86.PUSH_r, EAX);
745 asm.emitShort_Reg(x86.PUSH_r, EBX);
746 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
747 asm.emit2_Mem(x86.FADD_m32, 0, ESP);
748 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
749 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
750 asm.emitShort_Reg(x86.POP_r, EAX);
751 } else if (op instanceof Binary.SUB_F) {
752 asm.emitShort_Reg(x86.PUSH_r, EAX);
753 asm.emitShort_Reg(x86.PUSH_r, EBX);
754 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
755 asm.emit2_Mem(x86.FSUB_m32, 0, ESP);
756 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
757 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
758 asm.emitShort_Reg(x86.POP_r, EAX);
759 } else if (op instanceof Binary.MUL_F) {
760 asm.emitShort_Reg(x86.PUSH_r, EAX);
761 asm.emitShort_Reg(x86.PUSH_r, EBX);
762 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
763 asm.emit2_Mem(x86.FMUL_m32, 0, ESP);
764 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
765 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
766 asm.emitShort_Reg(x86.POP_r, EAX);
767 } else if (op instanceof Binary.DIV_F) {
768 asm.emitShort_Reg(x86.PUSH_r, EAX);
769 asm.emitShort_Reg(x86.PUSH_r, EBX);
770 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
771 asm.emit2_Mem(x86.FDIV_m32, 0, ESP);
772 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
773 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
774 asm.emitShort_Reg(x86.POP_r, EAX);
775 } else if (op instanceof Binary.REM_F) {
776 asm.emitShort_Reg(x86.PUSH_r, EAX);
777 asm.emitShort_Reg(x86.PUSH_r, EBX);
778 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
779 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
780 asm.emit2(x86.FPREM);
781 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
782 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
783 asm.emit2_FPReg(x86.FFREE, 0);
784 asm.emitShort_Reg(x86.POP_r, EAX);
785 } else if (op instanceof Binary.ADD_D) {
786 asm.emitShort_Reg(x86.PUSH_r, EDX);
787 asm.emitShort_Reg(x86.PUSH_r, EAX);
788 asm.emitShort_Reg(x86.PUSH_r, ECX);
789 asm.emitShort_Reg(x86.PUSH_r, EBX);
790 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
791 asm.emit2_Mem(x86.FADD_m64, 0, ESP);
792 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
793 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
794 asm.emitShort_Reg(x86.POP_r, EAX);
795 asm.emitShort_Reg(x86.POP_r, EDX);
796 } else if (op instanceof Binary.SUB_D) {
797 asm.emitShort_Reg(x86.PUSH_r, EDX);
798 asm.emitShort_Reg(x86.PUSH_r, EAX);
799 asm.emitShort_Reg(x86.PUSH_r, ECX);
800 asm.emitShort_Reg(x86.PUSH_r, EBX);
801 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
802 asm.emit2_Mem(x86.FSUB_m64, 0, ESP);
803 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
804 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
805 asm.emitShort_Reg(x86.POP_r, EAX);
806 asm.emitShort_Reg(x86.POP_r, EDX);
807 } else if (op instanceof Binary.MUL_D) {
808 asm.emitShort_Reg(x86.PUSH_r, EDX);
809 asm.emitShort_Reg(x86.PUSH_r, EAX);
810 asm.emitShort_Reg(x86.PUSH_r, ECX);
811 asm.emitShort_Reg(x86.PUSH_r, EBX);
812 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
813 asm.emit2_Mem(x86.FMUL_m64, 0, ESP);
814 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
815 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
816 asm.emitShort_Reg(x86.POP_r, EAX);
817 asm.emitShort_Reg(x86.POP_r, EDX);
818 } else if (op instanceof Binary.DIV_D) {
819 asm.emitShort_Reg(x86.PUSH_r, EDX);
820 asm.emitShort_Reg(x86.PUSH_r, EAX);
821 asm.emitShort_Reg(x86.PUSH_r, ECX);
822 asm.emitShort_Reg(x86.PUSH_r, EBX);
823 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
824 asm.emit2_Mem(x86.FDIV_m64, 0, ESP);
825 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
826 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
827 asm.emitShort_Reg(x86.POP_r, EAX);
828 asm.emitShort_Reg(x86.POP_r, EDX);
829 } else if (op instanceof Binary.REM_D) {
830 asm.emitShort_Reg(x86.PUSH_r, EDX);
831 asm.emitShort_Reg(x86.PUSH_r, EAX);
832 asm.emitShort_Reg(x86.PUSH_r, ECX);
833 asm.emitShort_Reg(x86.PUSH_r, EBX);
834 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
835 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
836 asm.emit2(x86.FPREM);
837 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
838 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
839 asm.emit2_FPReg(x86.FFREE, 0);
840 asm.emitShort_Reg(x86.POP_r, EAX);
841 asm.emitShort_Reg(x86.POP_r, EDX);
842 } else if (op instanceof Binary.SHL_I) {
843 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
844 asm.emit2_Reg(x86.SHL_r32_rc, EAX);
845 } else if (op instanceof Binary.SHR_I) {
846 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
847 asm.emit2_Reg(x86.SAR_r32_rc, EAX);
848 } else if (op instanceof Binary.USHR_I) {
849 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
850 asm.emit2_Reg(x86.SHR_r32_rc, EAX);
851 } else if (op instanceof Binary.SHL_L) {
852 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
853 asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
854 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
855 asm.emitCJUMP_Short(x86.JAE, (byte)0);
856 int cloc = asm.getCurrentOffset();
857 asm.emitSHLD_r_r_rc(EDX, EAX);
858 asm.emit2_Reg(x86.SHL_r32_rc, EAX);
859 asm.emitJUMP_Short(x86.JMP, (byte)0);
860 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
861 cloc = asm.getCurrentOffset();
862 asm.emit2_Reg_Reg(x86.MOV_r_r32, EDX, EAX);
863 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EAX);
864 asm.emit2_Reg(x86.SHL_r32_rc, EDX);
865 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
866 } else if (op instanceof Binary.SHR_L) {
867 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
868 asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
869 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
870 asm.emitCJUMP_Short(x86.JAE, (byte)0);
871 int cloc = asm.getCurrentOffset();
872 asm.emitSHRD_r_r_rc(EAX, EDX);
873 asm.emit2_Reg(x86.SAR_r32_rc, EDX);
874 asm.emitJUMP_Short(x86.JMP, (byte)0);
875 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
876 cloc = asm.getCurrentOffset();
877 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
878 asm.emit2_SHIFT_Reg_Imm8(x86.SAR_r32_i, EDX, (byte)31);
879 asm.emit2_Reg(x86.SAR_r32_rc, EAX);
880 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
881 } else if (op instanceof Binary.USHR_L) {
882 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
883 asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
884 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
885 asm.emitCJUMP_Short(x86.JAE, (byte)0);
886 int cloc = asm.getCurrentOffset();
887 asm.emitSHRD_r_r_rc(EAX, EDX);
888 asm.emit2_Reg(x86.SHR_r32_rc, EDX);
889 asm.emitJUMP_Short(x86.JMP, (byte)0);
890 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
891 cloc = asm.getCurrentOffset();
892 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
893 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EDX, EDX);
894 asm.emit2_Reg(x86.SHR_r32_rc, EAX);
895 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
896 } else if (op instanceof Binary.CMP_L) {
897 asm.emitARITH_Reg_Reg(x86.SUB_r_r32, EAX, EBX);
898 asm.emitARITH_Reg_Reg(x86.SBB_r_r32, EDX, ECX);
899 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
900 asm.emitCJUMP_Short(x86.JL, (byte)0);
901 int cloc1 = asm.getCurrentOffset();
902 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, ECX, ECX);
903 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, EDX);
904 asm.emitCJUMP_Short(x86.JE, (byte)0);
905 int cloc2 = asm.getCurrentOffset();
906 asm.emitShort_Reg(x86.INC_r32, ECX);
907 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
908 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
909 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
910 } else if (op instanceof Binary.CMP_FL) {
911 asm.emitShort_Reg(x86.PUSH_r, EAX);
912 asm.emitShort_Reg(x86.PUSH_r, EBX);
913 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
914 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
915 asm.emit2(x86.FUCOMPP);
916 asm.emit2(x86.FNSTSW_ax);
917 asm.emit1(x86.SAHF);
918 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
919 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
920 asm.emitCJUMP_Short(x86.JB, (byte)0);
921 int cloc1 = asm.getCurrentOffset();
922 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
923 asm.emitCJUMP_Short(x86.JE, (byte)0);
924 int cloc2 = asm.getCurrentOffset();
925 asm.emitShort_Reg(x86.INC_r32, ECX);
926 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
927 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
928 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
929 } else if (op instanceof Binary.CMP_FG) {
930 asm.emitShort_Reg(x86.PUSH_r, EAX);
931 asm.emitShort_Reg(x86.PUSH_r, EBX);
932 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
933 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
934 asm.emit2(x86.FUCOMPP);
935 asm.emit2(x86.FNSTSW_ax);
936 asm.emit1(x86.SAHF);
937 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
938 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 1);
939 asm.emitCJUMP_Short(x86.JB, (byte)0);
940 int cloc1 = asm.getCurrentOffset();
941 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
942 asm.emitCJUMP_Short(x86.JE, (byte)0);
943 int cloc2 = asm.getCurrentOffset();
944 asm.emitShort_Reg(x86.DEC_r32, ECX);
945 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
946 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
947 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
948 } else if (op instanceof Binary.CMP_DL) {
949 asm.emitShort_Reg(x86.PUSH_r, EDX);
950 asm.emitShort_Reg(x86.PUSH_r, EAX);
951 asm.emitShort_Reg(x86.PUSH_r, ECX);
952 asm.emitShort_Reg(x86.PUSH_r, EBX);
953 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
954 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
955 asm.emit2(x86.FUCOMPP);
956 asm.emit2(x86.FNSTSW_ax);
957 asm.emit1(x86.SAHF);
958 asm.emit2_Reg_Mem(x86.LEA, ESP, 16, ESP);
959 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
960 asm.emitCJUMP_Short(x86.JB, (byte)0);
961 int cloc1 = asm.getCurrentOffset();
962 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
963 asm.emitCJUMP_Short(x86.JE, (byte)0);
964 int cloc2 = asm.getCurrentOffset();
965 asm.emitShort_Reg(x86.INC_r32, ECX);
966 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
967 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
968 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
969 } else if (op instanceof Binary.CMP_DG) {
970 asm.emitShort_Reg(x86.PUSH_r, EDX);
971 asm.emitShort_Reg(x86.PUSH_r, EAX);
972 asm.emitShort_Reg(x86.PUSH_r, ECX);
973 asm.emitShort_Reg(x86.PUSH_r, EBX);
974 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
975 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
976 asm.emit2(x86.FUCOMPP);
977 asm.emit2(x86.FNSTSW_ax);
978 asm.emit1(x86.SAHF);
979 asm.emit2_Reg_Mem(x86.LEA, ESP, 16, ESP);
980 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 1);
981 asm.emitCJUMP_Short(x86.JB, (byte)0);
982 int cloc1 = asm.getCurrentOffset();
983 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
984 asm.emitCJUMP_Short(x86.JE, (byte)0);
985 int cloc2 = asm.getCurrentOffset();
986 asm.emitShort_Reg(x86.DEC_r32, ECX);
987 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
988 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
989 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
990 } else if (op instanceof Binary.ALIGN_P) {
991 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
992 asm.emitShort_Reg_Imm(x86.MOV_r_i32, EBX, 1);
993 asm.emit2_Reg(x86.SHL_r32_rc, EBX);
994 asm.emitShort_Reg(x86.DEC_r32, EBX);
995 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, EBX);
996 asm.emit2_Reg(x86.NOT_r32, EBX);
997 asm.emitARITH_Reg_Reg(x86.AND_r_r32, EAX, EBX);
998 }
999 else {
1000 Assert.UNREACHABLE(obj.toString());
1001 }
1002 storeOperand(Binary.getDest(obj), EAX);
1003 this.handled = true;
1004 }
1005 /***
1006 * @see joeq.Compiler.Quad.QuadVisitor#visitBoundsCheck(joeq.Compiler.Quad.Quad)
1007 */
1008 public void visitBoundsCheck(Quad obj) {
1009 if (TRACE) System.out.println(this+" BoundsCheck: "+obj);
1010 loadOperand(BoundsCheck.getRef(obj), EAX);
1011 loadOperand(BoundsCheck.getIndex(obj), EBX);
1012 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
1013 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
1014 this.handled = true;
1015 }
1016 /***
1017 * @see joeq.Compiler.Quad.QuadVisitor#visitCheckCast(joeq.Compiler.Quad.Quad)
1018 */
1019 public void visitCheckCast(Quad obj) {
1020 if (TRACE) System.out.println(this+" CheckCast: "+obj);
1021 loadOperand(CheckCast.getSrc(obj), EAX);
1022 asm.emitShort_Reg(x86.PUSH_r, EAX);
1023 jq_Type f = CheckCast.getType(obj).getType();
1024 emitPushAddressOf(f);
1025 emitCallRelative(TypeCheck._checkcast);
1026 storeOperand(CheckCast.getDest(obj), EAX);
1027 this.handled = true;
1028 }
1029 /***
1030 * @see joeq.Compiler.Quad.QuadVisitor#visitGetfield(joeq.Compiler.Quad.Quad)
1031 */
1032 public void visitGetfield(Quad obj) {
1033 if (TRACE) System.out.println(this+" Getfield: "+obj);
1034 jq_InstanceField f = (jq_InstanceField) Getfield.getField(obj).getField();
1035 loadOperand(Getfield.getBase(obj), EAX);
1036 asm.emitShort_Reg(x86.PUSH_r, EAX);
1037 if (f.getWidth() == 1) {
1038 if (f.needsDynamicLink(method)) {
1039
1040 asm.startDynamicPatch(10);
1041 emitPushAddressOf(f);
1042 emitCallRelative(x86ReferenceLinker._getfield1);
1043 asm.endDynamicPatch();
1044 } else {
1045 asm.emitShort_Reg(x86.POP_r, EAX);
1046 asm.emit3_Reg_Mem(x86.MOVSX_r_m8, EBX, f.getOffset(), EAX);
1047 asm.emitShort_Reg(x86.PUSH_r, EBX);
1048 }
1049 asm.emitShort_Reg(x86.POP_r, EAX);
1050 } else if (f.getWidth() == 4) {
1051 if (f.needsDynamicLink(method)) {
1052
1053 asm.startDynamicPatch(10);
1054 emitPushAddressOf(f);
1055 emitCallRelative(x86ReferenceLinker._getfield4);
1056 asm.endDynamicPatch();
1057 } else {
1058 asm.emitShort_Reg(x86.POP_r, EAX);
1059 asm.emit2_Mem(x86.PUSH_m, f.getOffset(), EAX);
1060 }
1061 asm.emitShort_Reg(x86.POP_r, EAX);
1062 } else if (f.getWidth() == 8) {
1063 if (f.needsDynamicLink(method)) {
1064
1065 asm.startDynamicPatch(13);
1066 emitPushAddressOf(f);
1067 emitCallRelative(x86ReferenceLinker._getfield8);
1068 asm.endDynamicPatch();
1069 } else {
1070 asm.emitShort_Reg(x86.POP_r, EAX);
1071 asm.emit2_Mem(x86.PUSH_m, f.getOffset()+4, EAX);
1072 asm.emit2_Mem(x86.PUSH_m, f.getOffset(), EAX);
1073 }
1074 asm.emitShort_Reg(x86.POP_r, EAX);
1075 asm.emitShort_Reg(x86.POP_r, EDX);
1076 } else if (f.getType() == jq_Primitive.SHORT) {
1077 if (f.needsDynamicLink(method)) {
1078
1079 asm.startDynamicPatch(10);
1080 emitPushAddressOf(f);
1081 emitCallRelative(x86ReferenceLinker._sgetfield);
1082 asm.endDynamicPatch();
1083 } else {
1084 asm.emitShort_Reg(x86.POP_r, EAX);
1085 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, EBX, f.getOffset(), EAX);
1086 asm.emitShort_Reg(x86.PUSH_r, EBX);
1087 }
1088 asm.emitShort_Reg(x86.POP_r, EAX);
1089 } else if (f.getType() == jq_Primitive.CHAR) {
1090 if (f.needsDynamicLink(method)) {
1091
1092 asm.startDynamicPatch(10);
1093 emitPushAddressOf(f);
1094 emitCallRelative(x86ReferenceLinker._cgetfield);
1095 asm.endDynamicPatch();
1096 } else {
1097 asm.emitShort_Reg(x86.POP_r, EAX);
1098 asm.emit3_Reg_Mem(x86.MOVZX_r_m16, EBX, f.getOffset(), EAX);
1099 asm.emitShort_Reg(x86.PUSH_r, EBX);
1100 }
1101 asm.emitShort_Reg(x86.POP_r, EAX);
1102 }
1103 else {
1104 Assert.UNREACHABLE();
1105 }
1106 storeOperand(Getfield.getDest(obj), EAX);
1107 this.handled = true;
1108 }
1109 /***
1110 * @see joeq.Compiler.Quad.QuadVisitor#visitGetstatic(joeq.Compiler.Quad.Quad)
1111 */
1112 public void visitGetstatic(Quad obj) {
1113 if (TRACE) System.out.println(this+" Getstatic: "+obj);
1114 jq_StaticField f = (jq_StaticField) Getstatic.getField(obj).getField();
1115 if (f.getWidth() == 8) {
1116 if (f.needsDynamicLink(method)) {
1117
1118 asm.startDynamicPatch(12);
1119 emitPushAddressOf(f);
1120 emitCallRelative(x86ReferenceLinker._getstatic8);
1121 asm.endDynamicPatch();
1122 } else {
1123 emitPushMemory(f);
1124 }
1125 asm.emitShort_Reg(x86.POP_r, EAX);
1126 asm.emitShort_Reg(x86.POP_r, EDX);
1127 } else {
1128 if (f.needsDynamicLink(method)) {
1129
1130 asm.startDynamicPatch(10);
1131 emitPushAddressOf(f);
1132 emitCallRelative(x86ReferenceLinker._getstatic4);
1133 asm.endDynamicPatch();
1134 } else {
1135 emitPushMemory(f);
1136 }
1137 asm.emitShort_Reg(x86.POP_r, EAX);
1138 }
1139 storeOperand(Getstatic.getDest(obj), EAX);
1140 this.handled = true;
1141 }
1142 /***
1143 * @see joeq.Compiler.Quad.QuadVisitor#visitGoto(joeq.Compiler.Quad.Quad)
1144 */
1145 public void visitGoto(Quad obj) {
1146 if (TRACE) System.out.println(this+" Goto: "+obj);
1147 branchHelper(BytecodeVisitor.CMP_UNCOND, Goto.getTarget(obj).getTarget());
1148 this.handled = true;
1149 }
1150 private void branchHelper(byte op, BasicBlock target) {
1151 if (op == BytecodeVisitor.CMP_UNCOND) {
1152 if (asm.containsTarget(target))
1153 asm.emitJUMP_Back(x86.JMP, target);
1154 else
1155 asm.emitJUMP_Forw(x86.JMP, target);
1156 } else {
1157 x86 opc = null;
1158 switch(op) {
1159 case BytecodeVisitor.CMP_EQ: opc = x86.JE; break;
1160 case BytecodeVisitor.CMP_NE: opc = x86.JNE; break;
1161 case BytecodeVisitor.CMP_LT: opc = x86.JL; break;
1162 case BytecodeVisitor.CMP_GE: opc = x86.JGE; break;
1163 case BytecodeVisitor.CMP_LE: opc = x86.JLE; break;
1164 case BytecodeVisitor.CMP_GT: opc = x86.JG; break;
1165 case BytecodeVisitor.CMP_AE: opc = x86.JAE; break;
1166 default: Assert.UNREACHABLE();
1167 }
1168 if (asm.containsTarget(target))
1169 asm.emitCJUMP_Back(opc, target);
1170 else
1171 asm.emitCJUMP_Forw(opc, target);
1172 }
1173 this.handled = true;
1174 }
1175 /***
1176 * @see joeq.Compiler.Quad.QuadVisitor#visitInstanceOf(joeq.Compiler.Quad.Quad)
1177 */
1178 public void visitInstanceOf(Quad obj) {
1179 if (TRACE) System.out.println(this+" InstanceOf: "+obj);
1180 loadOperand(InstanceOf.getSrc(obj), EAX);
1181 asm.emitShort_Reg(x86.PUSH_r, EAX);
1182 jq_Type f = InstanceOf.getType(obj).getType();
1183 emitPushAddressOf(f);
1184 emitCallRelative(TypeCheck._instance_of);
1185 storeOperand(InstanceOf.getDest(obj), EAX);
1186 this.handled = true;
1187 }
1188 /***
1189 * @see joeq.Compiler.Quad.QuadVisitor#visitIntIfCmp(joeq.Compiler.Quad.Quad)
1190 */
1191 public void visitIntIfCmp(Quad obj) {
1192 if (TRACE) System.out.println(this+" IntIfCmp: "+obj);
1193 loadOperand(IntIfCmp.getSrc1(obj), EAX);
1194 loadOperand(IntIfCmp.getSrc2(obj), ECX);
1195 asm.emitARITH_Reg_Reg(x86.CMP_r_r32, EAX, ECX);
1196 branchHelper(IntIfCmp.getCond(obj).getCondition(), IntIfCmp.getTarget(obj).getTarget());
1197 this.handled = true;
1198 }
1199 private void INVOKEDPATCHhelper(byte op, jq_Method f) {
1200 int dpatchsize;
1201 jq_StaticMethod dpatchentry;
1202 switch (op) {
1203 case BytecodeVisitor.INVOKE_VIRTUAL:
1204 dpatchsize = 16;
1205 dpatchentry = x86ReferenceLinker._invokevirtual;
1206 break;
1207 case BytecodeVisitor.INVOKE_STATIC:
1208 dpatchsize = 11;
1209 dpatchentry = x86ReferenceLinker._invokestatic;
1210 break;
1211 case BytecodeVisitor.INVOKE_SPECIAL:
1212 dpatchsize = 11;
1213 dpatchentry = x86ReferenceLinker._invokespecial;
1214 break;
1215 case BytecodeVisitor.INVOKE_INTERFACE:
1216
1217 default:
1218 throw new InternalError();
1219 }
1220
1221 asm.startDynamicPatch(dpatchsize);
1222 emitPushAddressOf(f);
1223 emitCallRelative(dpatchentry);
1224 asm.endDynamicPatch();
1225 this.handled = true;
1226 }
1227 private void INVOKENODPATCHhelper(byte op, jq_Method f) {
1228 switch(op) {
1229 case BytecodeVisitor.INVOKE_VIRTUAL: {
1230 int objptroffset = (f.getParamWords() << 2) - 4;
1231 int m_off = ((jq_InstanceMethod)f).getOffset();
1232 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, objptroffset, ESP);
1233 asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, ObjectLayout.VTABLE_OFFSET, EAX);
1234 asm.emit2_Mem(x86.CALL_m, m_off, EBX);
1235 break;
1236 }
1237 case BytecodeVisitor.INVOKE_SPECIAL:
1238 f = jq_Class.getInvokespecialTarget(method.getDeclaringClass(), (jq_InstanceMethod)f);
1239 emitCallRelative(f);
1240 break;
1241 case BytecodeVisitor.INVOKE_STATIC:
1242 emitCallRelative(f);
1243 break;
1244 case BytecodeVisitor.INVOKE_INTERFACE:
1245
1246 emitPushAddressOf(f);
1247 emitCallRelative(x86ReferenceLinker._invokeinterface);
1248
1249 asm.emit2_Reg_Mem(x86.LEA, ESP, f.getParamWords()<<2, ESP);
1250 break;
1251 default:
1252 Assert.UNREACHABLE();
1253 }
1254 this.handled = true;
1255 }
1256 private void INVOKEhelper(byte op, jq_Method f) {
1257 switch (op) {
1258 case BytecodeVisitor.INVOKE_VIRTUAL:
1259 if (f.needsDynamicLink(method))
1260 INVOKEDPATCHhelper(op, f);
1261 else
1262 INVOKENODPATCHhelper(op, f);
1263 break;
1264 case BytecodeVisitor.INVOKE_STATIC:
1265
1266 case BytecodeVisitor.INVOKE_SPECIAL:
1267 if (f.needsDynamicLink(method))
1268 INVOKEDPATCHhelper(op, f);
1269 else
1270 INVOKENODPATCHhelper(op, f);
1271 break;
1272 case BytecodeVisitor.INVOKE_INTERFACE:
1273 INVOKENODPATCHhelper(op, f);
1274 break;
1275 default:
1276 throw new InternalError();
1277 }
1278 this.handled = true;
1279 }
1280 /***
1281 * @see joeq.Compiler.Quad.QuadVisitor#visitInvoke(joeq.Compiler.Quad.Quad)
1282 */
1283 public void visitInvoke(Quad obj) {
1284 if (TRACE) System.out.println(this+" Invoke: "+obj);
1285 byte type = ((Invoke)obj.getOperator()).getType();
1286 ParamListOperand plo = Invoke.getParamList(obj);
1287 for (int i=0; i<plo.length(); ++i) {
1288 RegisterOperand r = plo.get(i);
1289 loadOperand(r, EAX);
1290 if (r.getType().getReferenceSize() == 8)
1291 asm.emitShort_Reg(x86.PUSH_r, EDX);
1292 asm.emitShort_Reg(x86.PUSH_r, EAX);
1293 }
1294 jq_Method f = Invoke.getMethod(obj).getMethod();
1295 INVOKEhelper(type, f);
1296
1297
1298 int diff = plo.words() - f.getParamWords();
1299 if (diff != 0)
1300 asm.emit2_Reg_Mem(x86.LEA, ESP, diff<<2, ESP);
1301
1302 jq_Type t = ((Invoke)obj.getOperator()).getReturnType();
1303 if (t.getReferenceSize() > 0) {
1304 storeOperand(Invoke.getDest(obj), EAX);
1305 }
1306 this.handled = true;
1307 }
1308 /***
1309 * @see joeq.Compiler.Quad.QuadVisitor#visitJsr(joeq.Compiler.Quad.Quad)
1310 */
1311 public void visitJsr(Quad obj) {
1312 if (TRACE) System.out.println(this+" Jsr: "+obj);
1313 BasicBlock succ = Jsr.getSuccessor(obj).getTarget();
1314 if (asm.containsTarget(succ)) {
1315 int offset = asm.getBranchTarget(succ);
1316 CodeAddress a = (CodeAddress) asm.getStartAddress().offset(offset);
1317 asm.emitShort_Reg_Imm(x86.MOV_r_i32, EAX, a.to32BitValue());
1318 Code2CodeReference r = new Code2CodeReference((CodeAddress) asm.getCurrentAddress().offset(-4), a);
1319 code_relocs.add(r);
1320 } else {
1321 asm.emitShort_Reg_Imm(x86.MOV_r_i32, EAX, 0x77777777);
1322 asm.recordAbsoluteReference(4, succ);
1323
1324 Code2CodeReference r = new Code2CodeReference((CodeAddress) asm.getCurrentAddress().offset(-4), null);
1325 code_relocs.add(r);
1326 }
1327 storeOperand(Jsr.getDest(obj), EAX);
1328 branchHelper(BytecodeVisitor.CMP_UNCOND, Jsr.getTarget(obj).getTarget());
1329 this.handled = true;
1330 }
1331 /***
1332 * @see joeq.Compiler.Quad.QuadVisitor#visitLookupSwitch(joeq.Compiler.Quad.Quad)
1333 */
1334 public void visitLookupSwitch(Quad obj) {
1335 if (TRACE) System.out.println(this+" LookupSwitch: "+obj);
1336 loadOperand(LookupSwitch.getSrc(obj), EAX);
1337 int n = LookupSwitch.getSize(obj);
1338 for (int i=0; i<n; ++i) {
1339 int match = LookupSwitch.getMatch(obj, i);
1340 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, match);
1341 BasicBlock target = LookupSwitch.getTarget(obj, i);
1342 branchHelper(BytecodeVisitor.CMP_EQ, target);
1343 }
1344 branchHelper(BytecodeVisitor.CMP_UNCOND, LookupSwitch.getDefault(obj).getTarget());
1345 this.handled = true;
1346 }
1347 /***
1348 * @see joeq.Compiler.Quad.QuadVisitor#visitMemLoad(joeq.Compiler.Quad.Quad)
1349 */
1350 public void visitMemLoad(Quad obj) {
1351 if (TRACE) System.out.println(this+" MemLoad: "+obj);
1352 loadOperand(MemLoad.getAddress(obj), EAX);
1353 MemLoad op = (MemLoad) obj.getOperator();
1354 if (op instanceof MemLoad.PEEK_1) {
1355 asm.emit3_Reg_Mem(x86.MOVSX_r_m8, ECX, 0, EAX);
1356 } else if (op instanceof MemLoad.PEEK_2) {
1357 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, ECX, 0, EAX);
1358 } else if (op instanceof MemLoad.PEEK_4) {
1359 asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, 0, EAX);
1360 } else if (op instanceof MemLoad.PEEK_8) {
1361 asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, 0, EAX);
1362 asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, 4, EAX);
1363 } else if (op instanceof MemLoad.PEEK_P) {
1364 asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, 0, EAX);
1365 }
1366 else {
1367 Assert.UNREACHABLE(obj.toString());
1368 }
1369 storeOperand(MemLoad.getDest(obj), ECX);
1370 this.handled = true;
1371 }
1372 /***
1373 * @see joeq.Compiler.Quad.QuadVisitor#visitMemStore(joeq.Compiler.Quad.Quad)
1374 */
1375 public void visitMemStore(Quad obj) {
1376 if (TRACE) System.out.println(this+" MemStore: "+obj);
1377 loadOperand(MemStore.getAddress(obj), EAX);
1378 loadOperand(MemStore.getValue(obj), EBX);
1379 MemStore op = (MemStore) obj.getOperator();
1380 if (op instanceof MemStore.POKE_1) {
1381 asm.emit2_Reg_Mem(x86.MOV_m_r8, EBX, 0, EAX);
1382 } else if (op instanceof MemStore.POKE_2) {
1383 asm.emitprefix(x86.PREFIX_16BIT);
1384 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1385 } else if (op instanceof MemStore.POKE_4) {
1386 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1387 } else if (op instanceof MemStore.POKE_8) {
1388 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1389 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, 4, EAX);
1390 } else if (op instanceof MemStore.POKE_P) {
1391 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1392 }
1393 else {
1394 Assert.UNREACHABLE(obj.toString());
1395 }
1396 this.handled = true;
1397 }
1398 /***
1399 * @see joeq.Compiler.Quad.QuadVisitor#visitMonitor(joeq.Compiler.Quad.Quad)
1400 */
1401 public void visitMonitor(Quad obj) {
1402 if (TRACE) System.out.println(this+" Monitor: "+obj);
1403 loadOperand(Monitor.getSrc(obj), EAX);
1404 asm.emitShort_Reg(x86.PUSH_r, EAX);
1405 jq_StaticMethod m = (obj.getOperator() instanceof Monitor.MONITORENTER)?joeq.Runtime.Monitor._monitorenter:joeq.Runtime.Monitor._monitorexit;
1406 emitCallRelative(m);
1407 this.handled = true;
1408 }
1409 /***
1410 * @see joeq.Compiler.Quad.QuadVisitor#visitMove(joeq.Compiler.Quad.Quad)
1411 */
1412 public void visitMove(Quad obj) {
1413 if (TRACE) System.out.println(this+" Move: "+obj);
1414
1415 RegisterOperand dest_o = Move.getDest(obj);
1416 Operand src_o = Move.getSrc(obj);
1417 loadOperand(src_o, EAX);
1418 storeOperand(dest_o, EAX);
1419 this.handled = true;
1420 }
1421 /***
1422 * @see joeq.Compiler.Quad.QuadVisitor#visitPhi(joeq.Compiler.Quad.Quad)
1423 */
1424 public void visitPhi(Quad obj) {
1425 if (TRACE) System.out.println(this+" Phi: "+obj);
1426 Assert.UNREACHABLE();
1427 }
1428 /***
1429 * @see joeq.Compiler.Quad.QuadVisitor#visitNew(joeq.Compiler.Quad.Quad)
1430 */
1431 public void visitNew(Quad obj) {
1432 if (TRACE) System.out.println(this+" New: "+obj);
1433 jq_Type f = New.getType(obj).getType();
1434 if (f.isClassType() && !f.needsDynamicLink(method)) {
1435 jq_Class k = (jq_Class)f;
1436 asm.emitPUSH_i(k.getInstanceSize());
1437 emitPushAddressOf(k.getVTable());
1438 emitCallRelative(DefaultHeapAllocator._allocateObject);
1439 } else {
1440 emitPushAddressOf(f);
1441 emitCallRelative(HeapAllocator._clsinitAndAllocateObject);
1442 }
1443 storeOperand(New.getDest(obj), EAX);
1444 this.handled = true;
1445 }
1446 /***
1447 * @see joeq.Compiler.Quad.QuadVisitor#visitNewArray(joeq.Compiler.Quad.Quad)
1448 */
1449 public void visitNewArray(Quad obj) {
1450 if (TRACE) System.out.println(this+" NewArray: "+obj);
1451 jq_Array f = (jq_Array) NewArray.getType(obj).getType();
1452
1453 if (!jq.RunningNative) {
1454
1455 } else {
1456 f.cls_initialize();
1457 }
1458 byte width = f.getLogElementSize();
1459 loadOperand(NewArray.getSize(obj), EAX);
1460 asm.emitShort_Reg(x86.PUSH_r, EAX);
1461 asm.emitShort_Reg(x86.PUSH_r, EAX);
1462 if (width != 0) asm.emit2_SHIFT_Mem_Imm8(x86.SHL_m32_i, 0, ESP, width);
1463 asm.emitARITH_Mem_Imm(x86.ADD_m_i32, 0, ESP, ObjectLayout.ARRAY_HEADER_SIZE);
1464 emitPushAddressOf(f.getVTable());
1465 emitCallRelative(DefaultHeapAllocator._allocateArray);
1466 storeOperand(NewArray.getDest(obj), EAX);
1467 this.handled = true;
1468 }
1469 /***
1470 * @see joeq.Compiler.Quad.QuadVisitor#visitNullCheck(joeq.Compiler.Quad.Quad)
1471 */
1472 public void visitNullCheck(Quad obj) {
1473 if (TRACE) System.out.println(this+" NullCheck: "+obj);
1474 loadOperand(NullCheck.getSrc(obj), EAX);
1475 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, 0, EAX);
1476 this.handled = true;
1477 }
1478 /***
1479 * @see joeq.Compiler.Quad.QuadVisitor#visitPutfield(joeq.Compiler.Quad.Quad)
1480 */
1481 public void visitPutfield(Quad obj) {
1482 if (TRACE) System.out.println(this+" Putfield: "+obj);
1483 jq_InstanceField f = (jq_InstanceField) Putfield.getField(obj).getField();
1484 loadOperand(Putfield.getBase(obj), EAX);
1485 asm.emitShort_Reg(x86.PUSH_r, EAX);
1486 loadOperand(Putfield.getSrc(obj), EAX);
1487 if (f.getWidth() == 8)
1488 asm.emitShort_Reg(x86.PUSH_r, EDX);
1489 asm.emitShort_Reg(x86.PUSH_r, EAX);
1490 if (f.getWidth() == 1) {
1491 if (f.needsDynamicLink(method)) {
1492
1493 asm.startDynamicPatch(10);
1494 emitPushAddressOf(f);
1495 emitCallRelative(x86ReferenceLinker._putfield1);
1496 asm.endDynamicPatch();
1497 } else {
1498
1499 asm.emitShort_Reg(x86.POP_r, EBX);
1500 asm.emitShort_Reg(x86.POP_r, EAX);
1501 asm.emit2_Reg_Mem(x86.MOV_m_r8, EBX, f.getOffset(), EAX);
1502 }
1503 } else if (f.getWidth() == 4) {
1504 if (f.needsDynamicLink(method)) {
1505
1506 asm.startDynamicPatch(10);
1507 emitPushAddressOf(f);
1508 emitCallRelative(x86ReferenceLinker._putfield4);
1509 asm.endDynamicPatch();
1510 } else {
1511
1512 asm.emitShort_Reg(x86.POP_r, EBX);
1513 asm.emitShort_Reg(x86.POP_r, EAX);
1514 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset(), EAX);
1515 }
1516 } else if (f.getWidth() == 8) {
1517 if (f.needsDynamicLink(method)) {
1518
1519 asm.startDynamicPatch(15);
1520 emitPushAddressOf(f);
1521 emitCallRelative(x86ReferenceLinker._putfield8);
1522 asm.endDynamicPatch();
1523 } else {
1524
1525 asm.emitShort_Reg(x86.POP_r, EBX);
1526 asm.emitShort_Reg(x86.POP_r, EAX);
1527 asm.emitShort_Reg(x86.POP_r, EDX);
1528 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset() , EDX);
1529 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, f.getOffset()+4, EDX);
1530 }
1531 } else if (f.getWidth() == 2) {
1532 if (f.needsDynamicLink(method)) {
1533
1534 asm.startDynamicPatch(10);
1535 emitPushAddressOf(f);
1536 emitCallRelative(x86ReferenceLinker._putfield2);
1537 asm.endDynamicPatch();
1538 } else {
1539
1540 asm.emitShort_Reg(x86.POP_r, EBX);
1541 asm.emitShort_Reg(x86.POP_r, EAX);
1542 asm.emitprefix(x86.PREFIX_16BIT);
1543 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset(), EAX);
1544 }
1545 }
1546 else {
1547 Assert.UNREACHABLE(obj.toString());
1548 }
1549 this.handled = true;
1550 }
1551 /***
1552 * @see joeq.Compiler.Quad.QuadVisitor#visitPutstatic(joeq.Compiler.Quad.Quad)
1553 */
1554 public void visitPutstatic(Quad obj) {
1555 if (TRACE) System.out.println(this+" Putstatic: "+obj);
1556 jq_StaticField f = (jq_StaticField) Putstatic.getField(obj).getField();
1557 loadOperand(Putstatic.getSrc(obj), EAX);
1558 if (f.getWidth() == 8) {
1559 asm.emitShort_Reg(x86.PUSH_r, EDX);
1560 asm.emitShort_Reg(x86.PUSH_r, EAX);
1561 if (f.needsDynamicLink(method)) {
1562
1563 asm.startDynamicPatch(12);
1564 emitPushAddressOf(f);
1565 emitCallRelative(x86ReferenceLinker._putstatic8);
1566 asm.endDynamicPatch();
1567 } else {
1568 emitPopMemory8(f);
1569 }
1570 } else {
1571 asm.emitShort_Reg(x86.PUSH_r, EAX);
1572 if (f.needsDynamicLink(method)) {
1573
1574 asm.startDynamicPatch(10);
1575 emitPushAddressOf(f);
1576 emitCallRelative(x86ReferenceLinker._putstatic4);
1577 asm.endDynamicPatch();
1578 } else {
1579 emitPopMemory(f);
1580 }
1581 }
1582 this.handled = true;
1583 }
1584 /***
1585 * @see joeq.Compiler.Quad.QuadVisitor#visitRet(joeq.Compiler.Quad.Quad)
1586 */
1587 public void visitRet(Quad obj) {
1588 if (TRACE) System.out.println(this+" Ret: "+obj);
1589 asm.emit2_Mem(x86.JMP_m, getStackOffset(Ret.getTarget(obj)), EBP);
1590 this.handled = true;
1591 }
1592 /***
1593 * @see joeq.Compiler.Quad.QuadVisitor#visitReturn(joeq.Compiler.Quad.Quad)
1594 */
1595 public void visitReturn(Quad obj) {
1596 if (TRACE) System.out.println(this+" Return: "+obj);
1597 Return o = (Return)obj.getOperator();
1598 if (o instanceof Return.THROW_A) {
1599 loadOperand(Return.getSrc(obj), EAX);
1600 asm.emitShort_Reg(x86.PUSH_r, EAX);
1601 emitCallRelative(ExceptionDeliverer._athrow);
1602 }
1603 if (method.isSynchronized()) SYNCHEXIThelper();
1604 if (TraceMethods) {
1605 emitPushAddressOf(SystemInterface.toCString("Leaving: "+method));
1606 emitCallMemory(SystemInterface._debugwriteln);
1607 }
1608 if (!(o instanceof Return.RETURN_V)) {
1609 loadOperand(Return.getSrc(obj), EAX);
1610 }
1611
1612 asm.emit1(x86.LEAVE);
1613 asm.emit1_Imm16(x86.RET_i, (char)(n_paramwords<<2));
1614 this.handled = true;
1615 }
1616 private void SYNCHEXIThelper() {
1617 if (method.isStatic()) {
1618 if (TraceQuads) {
1619 emitPushAddressOf(SystemInterface.toCString("exit: STATIC SYNCH EXIT"));
1620 emitCallMemory(SystemInterface._debugwriteln);
1621 }
1622
1623 Class c = Reflection.getJDKType(method.getDeclaringClass());
1624 Assert._assert(c != null);
1625 emitPushAddressOf(c);
1626 } else {
1627 if (TraceQuads) {
1628 emitPushAddressOf(SystemInterface.toCString("exit: INSTANCE SYNCH EXIT"));
1629 emitCallMemory(SystemInterface._debugwriteln);
1630 }
1631
1632 asm.emit2_Mem(x86.PUSH_m, getParamOffset(0), EBP);
1633 }
1634 emitCallRelative(joeq.Runtime.Monitor._monitorexit);
1635 this.handled = true;
1636 }
1637 /***
1638 * @see joeq.Compiler.Quad.QuadVisitor#visitSpecial(joeq.Compiler.Quad.Quad)
1639 */
1640 public void visitSpecial(Quad obj) {
1641 if (TRACE) System.out.println(this+" Special: "+obj);
1642 Special o = (Special) obj.getOperator();
1643 if (o instanceof Special.GET_EXCEPTION) {
1644
1645 } else if (o instanceof Special.GET_BASE_POINTER) {
1646 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EBP);
1647 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1648 } else if (o instanceof Special.GET_STACK_POINTER) {
1649 asm.emitShort_Reg(x86.PUSH_r, ESP);
1650 asm.emitShort_Reg(x86.POP_r, EAX);
1651 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1652 } else if (o instanceof Special.GET_THREAD_BLOCK) {
1653 asm.emitprefix(THREAD_BLOCK_PREFIX);
1654 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, THREAD_BLOCK_OFFSET);
1655 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1656 } else if (o instanceof Special.SET_THREAD_BLOCK) {
1657 loadOperand(Special.getOp2(obj), EAX);
1658 asm.emitprefix(THREAD_BLOCK_PREFIX);
1659 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, THREAD_BLOCK_OFFSET);
1660 } else if (o instanceof Special.ALLOCA) {
1661 loadOperand(Special.getOp2(obj), EAX);
1662 asm.emit2_Reg(x86.NEG_r32, EAX);
1663 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, ESP);
1664 asm.emit2_Reg_Reg(x86.MOV_r_r32, ESP, EAX);
1665 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1666 } else if (o instanceof Special.ATOMICADD_I) {
1667 loadOperand(Special.getOp2(obj), EAX);
1668 loadOperand(Special.getOp3(obj), EBX);
1669 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1670 asm.emitARITH_Reg_Mem(x86.ADD_m_r32, EBX, 0, EAX);
1671 } else if (o instanceof Special.ATOMICSUB_I) {
1672 loadOperand(Special.getOp2(obj), EAX);
1673 loadOperand(Special.getOp3(obj), EBX);
1674 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1675 asm.emitARITH_Reg_Mem(x86.SUB_m_r32, EBX, 0, EAX);
1676 } else if (o instanceof Special.ATOMICAND_I) {
1677 loadOperand(Special.getOp2(obj), EAX);
1678 loadOperand(Special.getOp3(obj), EBX);
1679 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1680 asm.emitARITH_Reg_Mem(x86.AND_m_r32, EBX, 0, EAX);
1681 } else if (o instanceof Special.ATOMICCAS4) {
1682 loadOperand(Special.getOp2(obj), ECX);
1683 loadOperand(Special.getOp3(obj), EAX);
1684 loadOperand(Special.getOp4(obj), EBX);
1685 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1686 asm.emit3_Reg_Mem(x86.CMPXCHG_32, EBX, 0, ECX);
1687 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1688 } else if (o instanceof Special.ATOMICCAS8) {
1689
1690 loadOperand(Special.getOp2(obj), EDI);
1691 loadOperand(Special.getOp3(obj), EAX);
1692 loadOperand(Special.getOp4(obj), EDI);
1693 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1694 asm.emit3_Reg_Mem(x86.CMPXCHG8B, EAX, 0, EDI);
1695 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1696 } else if (o instanceof Special.LONG_JUMP) {
1697 loadOperand(Special.getOp1(obj), ECX);
1698 loadOperand(Special.getOp3(obj), EBX);
1699 loadOperand(Special.getOp4(obj), EAX);
1700 loadOperand(Special.getOp2(obj), EBP);
1701 asm.emit2_Reg_Reg(x86.MOV_r_r32, ESP, EBX);
1702 asm.emit2_Reg(x86.JMP_r, ECX);
1703 } else if (o instanceof Special.POP_FP32) {
1704 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1705 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1706 asm.emitShort_Reg(x86.POP_r, EAX);
1707 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1708 } else if (o instanceof Special.POP_FP64) {
1709 asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1710 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1711 asm.emitShort_Reg(x86.POP_r, EAX);
1712 asm.emitShort_Reg(x86.POP_r, EDX);
1713 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1714 } else if (o instanceof Special.PUSH_FP32) {
1715 loadOperand(Special.getOp2(obj), EAX);
1716 asm.emitShort_Reg(x86.PUSH_r, EAX);
1717 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1718 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1719 } else if (o instanceof Special.PUSH_FP64) {
1720 loadOperand(Special.getOp2(obj), EAX);
1721 asm.emitShort_Reg(x86.PUSH_r, EDX);
1722 asm.emitShort_Reg(x86.PUSH_r, EAX);
1723 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1724 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1725 } else if (o instanceof Special.GET_EAX) {
1726 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1727 } else if (o instanceof Special.PUSHARG_I || o instanceof Special.PUSHARG_P) {
1728 loadOperand(Special.getOp2(obj), EAX);
1729 asm.emitShort_Reg(x86.PUSH_r, EAX);
1730 } else if (o instanceof Special.INVOKE_L || o instanceof Special.INVOKE_P) {
1731 loadOperand(Special.getOp2(obj), EAX);
1732 asm.emit2_Reg(x86.CALL_r, EAX);
1733 storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1734 } else if (o instanceof Special.ISEQ) {
1735 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1736 asm.emitCJUMP_Short(x86.JNE, (byte)0);
1737 int cloc = asm.getCurrentOffset();
1738 asm.emitShort_Reg(x86.INC_r32, ECX);
1739 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1740 storeOperand((RegisterOperand) Special.getOp1(obj), ECX);
1741 } else if (o instanceof Special.ISGE) {
1742 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1743 asm.emitCJUMP_Short(x86.JL, (byte)0);
1744 int cloc = asm.getCurrentOffset();
1745 asm.emitShort_Reg(x86.INC_r32, ECX);
1746 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1747 storeOperand((RegisterOperand) Special.getOp1(obj), ECX);
1748 }
1749 else {
1750 Assert.UNREACHABLE(obj.toString());
1751 }
1752 this.handled = true;
1753 }
1754 /***
1755 * @see joeq.Compiler.Quad.QuadVisitor#visitStoreCheck(joeq.Compiler.Quad.Quad)
1756 */
1757 public void visitStoreCheck(Quad obj) {
1758 if (TRACE) System.out.println(this+" StoreCheck: "+obj);
1759 loadOperand(StoreCheck.getElement(obj), EAX);
1760 asm.emitShort_Reg(x86.PUSH_r, EAX);
1761 loadOperand(StoreCheck.getRef(obj), EAX);
1762 asm.emitShort_Reg(x86.PUSH_r, EAX);
1763 emitCallRelative(TypeCheck._arrayStoreCheck);
1764 this.handled = true;
1765 }
1766 /***
1767 * @see joeq.Compiler.Quad.QuadVisitor#visitTableSwitch(joeq.Compiler.Quad.Quad)
1768 */
1769 public void visitTableSwitch(Quad obj) {
1770 if (TRACE) System.out.println(this+" TableSwitch: "+obj);
1771 int low = TableSwitch.getLow(obj).getValue();
1772 BasicBlockTableOperand targets = TableSwitch.getTargetTable(obj);
1773
1774 loadOperand(TableSwitch.getSrc(obj), EAX);
1775 if (low != 0)
1776 asm.emitARITH_Reg_Imm(x86.SUB_r_i32, EAX, low);
1777 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, targets.size());
1778 branchHelper(BytecodeVisitor.CMP_AE, TableSwitch.getDefault(obj).getTarget());
1779 asm.emitCALL_rel32(x86.CALL_rel32, 0);
1780 int cloc = asm.getCurrentOffset();
1781 asm.emitShort_Reg(x86.POP_r, ECX);
1782
1783 asm.emit2_Reg_Mem(x86.LEA, EDX, ECX, EAX, SCALE_4, 127);
1784 int cloc2 = asm.getCurrentOffset();
1785 asm.emitARITH_Reg_Mem(x86.ADD_r_m32, EDX, -4, EDX);
1786 asm.emit2_Reg(x86.JMP_r, EDX);
1787 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc+4));
1788 for (int i=0; i<targets.size(); ++i) {
1789 BasicBlock target = targets.get(i);
1790 if (asm.containsTarget(target)) {
1791 int offset = asm.getBranchTarget(target) - asm.getCurrentOffset() + 4;
1792 asm.emitDATA(offset);
1793 } else {
1794 asm.emitDATA(0x77777777);
1795 asm.recordForwardBranch(4, target);
1796 }
1797 }
1798 this.handled = true;
1799 }
1800 /***
1801 * @see joeq.Compiler.Quad.QuadVisitor#visitUnary(joeq.Compiler.Quad.Quad)
1802 */
1803 public void visitUnary(Quad obj) {
1804 if (TRACE) System.out.println(this+" Unary: "+obj);
1805 loadOperand(Unary.getSrc(obj), EAX);
1806 Unary op = (Unary) obj.getOperator();
1807 if (op instanceof Unary.NEG_I) {
1808 asm.emit2_Reg(x86.NEG_r32, EAX);
1809 } else if (op instanceof Unary.NEG_L) {
1810 asm.emit2_Reg(x86.NEG_r32, EDX);
1811 asm.emit2_Reg(x86.NEG_r32, EAX);
1812 asm.emitARITH_Reg_Imm(x86.SBB_r_i32, EDX, 0);
1813 } else if (op instanceof Unary.NEG_F) {
1814 asm.emitShort_Reg(x86.PUSH_r, EAX);
1815 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1816 asm.emit2(x86.FCHS);
1817 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1818 asm.emitShort_Reg(x86.POP_r, EAX);
1819 } else if (op instanceof Unary.NEG_D) {
1820 asm.emitShort_Reg(x86.PUSH_r, EDX);
1821 asm.emitShort_Reg(x86.PUSH_r, EAX);
1822 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1823 asm.emit2(x86.FCHS);
1824 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1825 asm.emitShort_Reg(x86.POP_r, EAX);
1826 asm.emitShort_Reg(x86.POP_r, EDX);
1827 } else if (op instanceof Unary.INT_2LONG) {
1828 asm.emit1(x86.CWD);
1829 } else if (op instanceof Unary.INT_2FLOAT) {
1830 asm.emitShort_Reg(x86.PUSH_r, EAX);
1831 asm.emit2_Mem(x86.FILD_m32, 0, ESP);
1832 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1833 asm.emitShort_Reg(x86.POP_r, EAX);
1834 } else if (op instanceof Unary.INT_2DOUBLE) {
1835 asm.emitShort_Reg(x86.PUSH_r, EAX);
1836 asm.emit2_Mem(x86.FILD_m32, 0, ESP);
1837 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1838 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1839 asm.emitShort_Reg(x86.POP_r, EAX);
1840 asm.emitShort_Reg(x86.POP_r, EDX);
1841 } else if (op instanceof Unary.LONG_2INT) {
1842 } else if (op instanceof Unary.LONG_2FLOAT) {
1843 asm.emitShort_Reg(x86.PUSH_r, EDX);
1844 asm.emitShort_Reg(x86.PUSH_r, EAX);
1845 asm.emit2_Mem(x86.FILD_m64, 0, ESP);
1846 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1847 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1848 asm.emitShort_Reg(x86.POP_r, EAX);
1849 } else if (op instanceof Unary.LONG_2DOUBLE) {
1850 asm.emitShort_Reg(x86.PUSH_r, EDX);
1851 asm.emitShort_Reg(x86.PUSH_r, EAX);
1852 asm.emit2_Mem(x86.FILD_m64, 0, ESP);
1853 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1854 asm.emitShort_Reg(x86.POP_r, EAX);
1855 asm.emitShort_Reg(x86.POP_r, EDX);
1856 } else if (op instanceof Unary.FLOAT_2INT) {
1857 asm.emitShort_Reg(x86.PUSH_r, EAX);
1858 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1859 toIntHelper();
1860 asm.emitShort_Reg(x86.POP_r, EAX);
1861 } else if (op instanceof Unary.FLOAT_2LONG) {
1862 asm.emitShort_Reg(x86.PUSH_r, EAX);
1863 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1864 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1865 toLongHelper();
1866 asm.emitShort_Reg(x86.POP_r, EAX);
1867 asm.emitShort_Reg(x86.POP_r, EDX);
1868 } else if (op instanceof Unary.FLOAT_2DOUBLE) {
1869 asm.emitShort_Reg(x86.PUSH_r, EAX);
1870 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1871 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1872 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1873 asm.emitShort_Reg(x86.POP_r, EAX);
1874 asm.emitShort_Reg(x86.POP_r, EDX);
1875 } else if (op instanceof Unary.DOUBLE_2INT) {
1876 asm.emitShort_Reg(x86.PUSH_r, EDX);
1877 asm.emitShort_Reg(x86.PUSH_r, EAX);
1878 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1879 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1880 toIntHelper();
1881 asm.emitShort_Reg(x86.POP_r, EAX);
1882 } else if (op instanceof Unary.DOUBLE_2LONG) {
1883 asm.emitShort_Reg(x86.PUSH_r, EDX);
1884 asm.emitShort_Reg(x86.PUSH_r, EAX);
1885 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1886 toLongHelper();
1887 asm.emitShort_Reg(x86.POP_r, EAX);
1888 asm.emitShort_Reg(x86.POP_r, EDX);
1889 } else if (op instanceof Unary.DOUBLE_2FLOAT) {
1890 asm.emitShort_Reg(x86.PUSH_r, EDX);
1891 asm.emitShort_Reg(x86.PUSH_r, EAX);
1892 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1893 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1894 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1895 asm.emitShort_Reg(x86.POP_r, EAX);
1896 } else if (op instanceof Unary.INT_2BYTE) {
1897 asm.emit3_Reg_Reg(x86.MOVSX_r_r8, EAX, AL);
1898 } else if (op instanceof Unary.INT_2SHORT) {
1899 asm.emit3_Reg_Reg(x86.MOVSX_r_r16, EAX, AX);
1900 } else if (op instanceof Unary.INT_2CHAR) {
1901 asm.emit3_Reg_Reg(x86.MOVZX_r_r16, EAX, AX);
1902 } else if (op instanceof Unary.FLOAT_2INTBITS) {
1903
1904 } else if (op instanceof Unary.INTBITS_2FLOAT) {
1905
1906 } else if (op instanceof Unary.DOUBLE_2LONGBITS) {
1907
1908 } else if (op instanceof Unary.LONGBITS_2DOUBLE) {
1909
1910 } else if (op instanceof Unary.OBJECT_2ADDRESS) {
1911
1912 } else if (op instanceof Unary.ADDRESS_2OBJECT) {
1913
1914 } else if (op instanceof Unary.INT_2ADDRESS) {
1915
1916 } else if (op instanceof Unary.ADDRESS_2INT) {
1917
1918 } else if (op instanceof Unary.ISNULL_P) {
1919 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1920 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, 0);
1921 asm.emitCJUMP_Short(x86.JNE, (byte)0);
1922 int cloc = asm.getCurrentOffset();
1923 asm.emitShort_Reg(x86.INC_r32, ECX);
1924 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1925 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
1926 }
1927 else {
1928 Assert.UNREACHABLE(obj.toString());
1929 }
1930 storeOperand(Binary.getDest(obj), EAX);
1931 this.handled = true;
1932 }
1933 private void toIntHelper() {
1934
1935 emitFLD64(MathSupport._maxint);
1936 asm.emit2_FPReg(x86.FUCOMIP, 1);
1937 asm.emitCJUMP_Short(x86.JP, (byte)0);
1938 int cloc1 = asm.getCurrentOffset();
1939
1940 asm.emitCJUMP_Short(x86.JBE, (byte)0);
1941 int cloc2 = asm.getCurrentOffset();
1942
1943 emitFLD64(MathSupport._minint);
1944 asm.emit2_FPReg(x86.FUCOMIP, 1);
1945 asm.emitCJUMP_Short(x86.JAE, (byte)0);
1946 int cloc3 = asm.getCurrentOffset();
1947
1948 asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1949 {
1950 asm.emit2_Mem(x86.FNSTCW, 4, ESP);
1951 asm.emit2_Mem(x86.FNSTCW, 0, ESP);
1952 asm.emitARITH_Mem_Imm(x86.OR_m_i32, 4, ESP, 0x0c00);
1953 asm.emit2(x86.FNCLEX);
1954 asm.emit2_Mem(x86.FLDCW, 4, ESP);
1955 }
1956 asm.emit2_Mem(x86.FISTP_m32, 8, ESP);
1957 {
1958
1959 asm.emit2(x86.FNCLEX);
1960 asm.emit2_Mem(x86.FLDCW, 0, ESP);
1961 }
1962 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1963 asm.emitJUMP_Short(x86.JMP, (byte)0);
1964 int cloc4 = asm.getCurrentOffset();
1965 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
1966
1967 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, 0);
1968 asm.emitJUMP_Short(x86.JMP, (byte)0);
1969 int cloc5 = asm.getCurrentOffset();
1970 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
1971
1972 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, Integer.MAX_VALUE);
1973 asm.emitJUMP_Short(x86.JMP, (byte)0);
1974 int cloc6 = asm.getCurrentOffset();
1975 asm.patch1(cloc3-1, (byte)(asm.getCurrentOffset()-cloc3));
1976
1977 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, Integer.MIN_VALUE);
1978 asm.patch1(cloc5-1, (byte)(asm.getCurrentOffset()-cloc5));
1979 asm.patch1(cloc6-1, (byte)(asm.getCurrentOffset()-cloc6));
1980 asm.emit2_FPReg(x86.FFREE, 0);
1981 asm.patch1(cloc4-1, (byte)(asm.getCurrentOffset()-cloc4));
1982 this.handled = true;
1983 }
1984 private void toLongHelper() {
1985
1986 emitFLD64(MathSupport._maxlong);
1987 asm.emit2_FPReg(x86.FUCOMIP, 1);
1988 asm.emitCJUMP_Short(x86.JP, (byte)0);
1989 int cloc1 = asm.getCurrentOffset();
1990
1991 asm.emitCJUMP_Short(x86.JBE, (byte)0);
1992 int cloc2 = asm.getCurrentOffset();
1993
1994 emitFLD64(MathSupport._minlong);
1995 asm.emit2_FPReg(x86.FUCOMIP, 1);
1996 asm.emitCJUMP_Short(x86.JAE, (byte)0);
1997 int cloc3 = asm.getCurrentOffset();
1998
1999 asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
2000 {
2001 asm.emit2_Mem(x86.FNSTCW, 4, ESP);
2002 asm.emit2_Mem(x86.FNSTCW, 0, ESP);
2003 asm.emitARITH_Mem_Imm(x86.OR_m_i32, 4, ESP, 0x0c00);
2004 asm.emit2(x86.FNCLEX);
2005 asm.emit2_Mem(x86.FLDCW, 4, ESP);
2006 }
2007 asm.emit2_Mem(x86.FISTP_m64, 8, ESP);
2008 {
2009
2010 asm.emit2(x86.FNCLEX);
2011 asm.emit2_Mem(x86.FLDCW, 0, ESP);
2012 }
2013 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
2014 asm.emitJUMP_Short(x86.JMP, (byte)0);
2015 int cloc4 = asm.getCurrentOffset();
2016 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
2017
2018 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, 0);
2019 asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, 0);
2020 asm.emitJUMP_Short(x86.JMP, (byte)0);
2021 int cloc5 = asm.getCurrentOffset();
2022 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
2023
2024 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, (int)Long.MAX_VALUE);
2025 asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, (int)(Long.MAX_VALUE>>32));
2026 asm.emitJUMP_Short(x86.JMP, (byte)0);
2027 int cloc6 = asm.getCurrentOffset();
2028 asm.patch1(cloc3-1, (byte)(asm.getCurrentOffset()-cloc3));
2029
2030 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, (int)Long.MIN_VALUE);
2031 asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, (int)(Long.MIN_VALUE>>32));
2032 asm.patch1(cloc5-1, (byte)(asm.getCurrentOffset()-cloc5));
2033 asm.patch1(cloc6-1, (byte)(asm.getCurrentOffset()-cloc6));
2034 asm.emit2_FPReg(x86.FFREE, 0);
2035 asm.patch1(cloc4-1, (byte)(asm.getCurrentOffset()-cloc4));
2036 this.handled = true;
2037 }
2038 /***
2039 * @see joeq.Compiler.Quad.QuadVisitor#visitZeroCheck(joeq.Compiler.Quad.Quad)
2040 */
2041 public void visitZeroCheck(Quad obj) {
2042 if (TRACE) System.out.println(this+" ZeroCheck: "+obj);
2043 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EAX);
2044 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EDX, EDX);
2045 loadOperand(ZeroCheck.getSrc(obj), EBX);
2046 asm.emit2_Reg(x86.IDIV_r32, EBX);
2047 this.handled = true;
2048 }
2049 boolean handled;
2050 /***
2051 * @see joeq.Compiler.Quad.QuadVisitor#visitQuad(joeq.Compiler.Quad.Quad)
2052 */
2053 public void visitQuad(Quad obj) {
2054 Assert._assert(handled, obj.toString());
2055 }
2056
2057 public static void main(String[] args) {
2058 HostedVM.initialize();
2059 CodeAddress.FACTORY = joeq.Bootstrap.BootstrapCodeAddress.FACTORY;
2060 HeapAddress.FACTORY = joeq.Bootstrap.BootstrapHeapAddress.FACTORY;
2061 ClassLibInterface.useJoeqClasslib(true);
2062 CodeAllocator.initializeCompiledMethodMap();
2063 BootstrapCodeAllocator bca = BootstrapCodeAllocator.DEFAULT;
2064 DefaultCodeAllocator.default_allocator = bca;
2065
2066 bca.init();
2067 ObjectTraverser obj_trav = ClassLibInterface.DEFAULT.getObjectTraverser();
2068 Reflection.obj_trav = obj_trav;
2069 obj_trav.initialize();
2070 SinglePassBootImage objmap = SinglePassBootImage.DEFAULT;
2071
2072
2073 objmap.enableAllocations();
2074
2075 String className = args[0];
2076 jq_Class c = (jq_Class) jq_Type.parseType(className);
2077 c.cls_initialize();
2078
2079 ALWAYS_TRACE = true;
2080 x86Assembler.TRACE = true;
2081
2082 Iterator i = Arrays.asList(c.getDeclaredStaticMethods()).iterator();
2083 i = new AppendIterator(i, Arrays.asList(c.getDeclaredInstanceMethods()).iterator());
2084 while (i.hasNext()) {
2085 jq_Method m = (jq_Method) i.next();
2086 if (m.getBytecode() != null) {
2087 ControlFlowGraph cfg = CodeCache.getCode(m);
2088 SimpleCompiler compiler = new SimpleCompiler(cfg);
2089 jq_CompiledCode cc = compiler.compile();
2090 m.setDefaultCompiledVersion(cc);
2091 }
2092 }
2093 }
2094
2095 }